using System;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// 消息类
/// </summary>
public class Message : IEnumerable<KeyValuePair<string, object>>
{
    //存储消息的字典
    private Dictionary<string, object> dicDatas = null;

    public string Name { get; private set; }//消息名，不能设置，要在构造函数里设置
    public object Sender { get; private set; }//发送者
    public object Content { get; set; }//发送的内容

    /// <summary>
    /// 索引器方法实现，对字典进行复制和取值
    /// </summary>
    /// <param name="key">Key.</param>
    public object this[string key]
    {
        get
        {
            if (null == dicDatas || !dicDatas.ContainsKey(key))//如果字典为空，或key键为空（判断字典里是否存在 key 键）
                return null;//返回空
            return dicDatas[key];//返回key对应的值
        }
        set
        {
            if (null == dicDatas)//如果字典为空
                dicDatas = new Dictionary<string, object>();//new一个
            if (dicDatas.ContainsKey(key))//如果字典里包含key
                dicDatas[key] = value;//为key键赋对应值
            else
                dicDatas.Add(key, value);//如果没有key键值，直接添加key键值
        }
    }


    #region 实现接口
    /// <summary>
    /// 实现接口
    /// </summary>
    /// <returns></returns>
    public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
    {
        if (null == dicDatas)//如果字典为空
            yield break;//打断它
        foreach (KeyValuePair<string, object> kvp in dicDatas)//不等于空的时候，进行遍历
        {
            yield return kvp;//返回
        }
    }

    /// <summary>
    /// 实现接口
    /// 用字典自己的GetEnumerator方法，完成消息体的迭代
    /// </summary>
    /// <returns></returns>
    IEnumerator IEnumerable.GetEnumerator()
    {
        return dicDatas.GetEnumerator();
    }
    #endregion

    //*********************************************************************
    // GetEnumerator是返回实例的枚举数。换句话说就是返回集的中所有元素一个一个列出来。
    // 我们可以通过MoveNext()得到集合中的所有元素。这里的名词稍微说明一下，
    // 枚举就：是一个一个的列举。
    // 枚举数：是循环访问其关联集合的对象。它提供一种方法帮助你遍历一个集合。
    //*********************************************************************
    //*********************************************************************
    // keyValuePair翻译过来就是键值对，也就是一个一对一的数据类型，
    // 它是值类型，可以理解为Dictionary(字典)的基本单元。
    // 它有两个属性，Key和Value。
    // 本质上来讲，它就是C#中很多个数据类型之一。你可以这么用。
    // KeyValuePair<string, string> data1 = new KeyValuePair<string, string>("001", "John");
    // Console.WriteLine(data1.Key);
    // 类比理解一下Size类型，有Width和Height两个属性。应该可以想明白了。
    //*********************************************************************

    #region Message 构造函数
    /// <summary>
    /// Message构造函数
    /// </summary>
    /// <param name="name">消息名</param>
    /// <param name="sender">发送者.</param>
    public Message(string name, object sender)
    {
        Name = name;
        Sender = sender;
        Content = null;
    }

    /// <summary>
    /// Message构造函数
    /// </summary>
    /// <param name="name">消息名.</param>
    /// <param name="sender">发送者.</param>
    /// <param name="content">发送的内容.</param>
    public Message(string name, object sender, object content)
    {
        Name = name;
        Sender = sender;
        Content = content;
    }

    /// <summary>
    /// Message构造函数
    /// </summary>
    /// <param name="name">消息名.</param>
    /// <param name="sender">发送者.</param>
    /// <param name="content">发送的内容.</param>
    /// <param name="_dicParams">可变参数.</param>
    public Message(string name, object sender, object content, params object[] _dicParams)
    {
        Name = name;
        Sender = sender;
        Content = content;
        //判断可变参数是否为 Dictionary<string, object> 类型，即是我们的消息体字典类型的时候，我们才给它赋值
        if (_dicParams.GetType() == typeof(Dictionary<string, object>))
        {
            foreach (object _dicParam in _dicParams)//遍历
            {
                //遍历字典
                foreach (KeyValuePair<string, object> kvp in _dicParam as Dictionary<string, object>)
                {
                    //dicDatas[kvp.Key] = kvp.Value;  //error
                    //通过索引器为字典赋值
                    this[kvp.Key] = kvp.Value;
                }
            }
        }
    }

    /// <summary>
    /// Message构造函数
    /// 此函数为：复制构造函数，即把一个对象复制给另一个对象
    /// </summary>
    /// <param name="message">Message类型参数.</param>
    public Message(Message message)
    {
        Name = message.Name;
        Sender = message.Sender;
        Content = message.Content;
        //遍历字典，通过索引器为字典赋值
        foreach (KeyValuePair<string, object> kvp in message.dicDatas)
        {
            this[kvp.Key] = kvp.Value;
        }
    }
    #endregion


    #region Add & Remove
    /// <summary>
    /// 添加的方法
    /// </summary>
    /// <param name="key">Key.</param>
    /// <param name="value">Value.</param>
    public void Add(string key, object value)
    {
        this[key] = value;
    }

    /// <summary>
    /// 移除的方法
    /// </summary>
    /// <param name="key">Key.</param>
    public void Remove(string key)
    {
        if (null != dicDatas && dicDatas.ContainsKey(key))
        {
            dicDatas.Remove(key);
        }
    }
    #endregion


    #region Send()
    /// <summary>
    /// 发送的方法
    /// </summary>
    public void Send()
    {
        //调用MessageCenter的SendMessage方法
        MessageCenter.Instance.SendMessage(this);
    }
    #endregion
}

//综上所述，一个类型是否支持foreach遍历，必须满足下面条件：
//方案1：让这个类实现IEnumerable接口 
//方案2：这个类有一个public的GetEnumerator的实例方法，并且返回类型中有public 的bool MoveNext()实例方法和public的Current实例属性。

